package com.wysiwyg.common.web.handle;

import com.wysiwyg.common.exception.BusinessException;
import com.wysiwyg.common.web.response.ResponseEnum;
import com.wysiwyg.common.web.response.ServerResponseEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.util.HashMap;
import java.util.Map;

/**
 * 全局异常处理器
 * @author wwcc
 * @date 2024/11/14 20:52:48
 */
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理参数校验异常
     */
    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    @ResponseBody
    public ResponseEntity<ServerResponseEntity<Map<String, String>>> handleValidationException(Exception ex) {
        Map<String, String> errors = new HashMap<>();
        
        if (ex instanceof MethodArgumentNotValidException validEx) {
            for (FieldError error : validEx.getBindingResult().getFieldErrors()) {
                errors.put(error.getField(), error.getDefaultMessage());
            }
        } else if (ex instanceof BindException bindEx) {
            for (FieldError error : bindEx.getBindingResult().getFieldErrors()) {
                errors.put(error.getField(), error.getDefaultMessage());
            }
        }
        
        log.warn("参数校验失败: {}", errors);
        return ResponseEntity.badRequest()
                .body(ServerResponseEntity.fail(ResponseEnum.PARAM_ERROR, errors));
    }

    /**
     * 处理参数类型不匹配异常
     */
    @ExceptionHandler({MethodArgumentTypeMismatchException.class, MissingServletRequestParameterException.class})
    @ResponseBody
    public ResponseEntity<ServerResponseEntity<String>> handleParameterException(Exception ex) {
        log.warn("参数类型不匹配: {}", ex.getMessage());
        return ResponseEntity.badRequest()
                .body(ServerResponseEntity.fail(ResponseEnum.PARAM_ERROR, ex.getMessage()));
    }

    /**
     * 处理业务逻辑异常
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public ResponseEntity<ServerResponseEntity<String>> handleBusinessException(BusinessException ex) {
        log.warn("业务异常: {}", ex.getMessage());
        return ResponseEntity.status(ex.getResponseEnum().getHttpStatus())
                .body(ServerResponseEntity.fail(ex.getResponseEnum(), ex.getMessage()));
    }

    /**
     * 处理所有未捕获的异常
     */
    @ExceptionHandler(Throwable.class)
    @ResponseBody
    public ResponseEntity<ServerResponseEntity<String>> handleException(Throwable ex) {
        log.error("系统异常: {}", ex.getMessage(), ex);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ServerResponseEntity.fail(ResponseEnum.SYSTEM_BUSY));
    }
}